prtape-cli 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +138 -2
- package/dist/adapters/claude.d.ts +2 -0
- package/dist/adapters/claude.js +309 -0
- package/dist/adapters/claude.js.map +1 -0
- package/dist/bash-edits.d.ts +41 -0
- package/dist/bash-edits.js +440 -0
- package/dist/bash-edits.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +214 -0
- package/dist/cli.js.map +1 -0
- package/dist/decision.d.ts +7 -0
- package/dist/decision.js +224 -0
- package/dist/decision.js.map +1 -0
- package/dist/discover.d.ts +32 -0
- package/dist/discover.js +179 -0
- package/dist/discover.js.map +1 -0
- package/dist/display.d.ts +28 -0
- package/dist/display.js +311 -0
- package/dist/display.js.map +1 -0
- package/dist/env.d.ts +5 -0
- package/dist/env.js +11 -0
- package/dist/env.js.map +1 -0
- package/dist/gh.d.ts +46 -0
- package/dist/gh.js +190 -0
- package/dist/gh.js.map +1 -0
- package/dist/glance.d.ts +15 -0
- package/dist/glance.js +75 -0
- package/dist/glance.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/orphan.d.ts +44 -0
- package/dist/orphan.js +152 -0
- package/dist/orphan.js.map +1 -0
- package/dist/png.d.ts +2 -0
- package/dist/png.js +13 -0
- package/dist/png.js.map +1 -0
- package/dist/privacy.d.ts +7 -0
- package/dist/privacy.js +39 -0
- package/dist/privacy.js.map +1 -0
- package/dist/redact.d.ts +17 -0
- package/dist/redact.js +101 -0
- package/dist/redact.js.map +1 -0
- package/dist/run.d.ts +48 -0
- package/dist/run.js +218 -0
- package/dist/run.js.map +1 -0
- package/dist/summary.d.ts +7 -0
- package/dist/summary.js +134 -0
- package/dist/summary.js.map +1 -0
- package/dist/tests-detect.d.ts +19 -0
- package/dist/tests-detect.js +97 -0
- package/dist/tests-detect.js.map +1 -0
- package/dist/text.d.ts +8 -0
- package/dist/text.js +31 -0
- package/dist/text.js.map +1 -0
- package/dist/timeline/format.d.ts +28 -0
- package/dist/timeline/format.js +127 -0
- package/dist/timeline/format.js.map +1 -0
- package/dist/timeline/md.d.ts +17 -0
- package/dist/timeline/md.js +129 -0
- package/dist/timeline/md.js.map +1 -0
- package/dist/timeline/svg.d.ts +7 -0
- package/dist/timeline/svg.js +260 -0
- package/dist/timeline/svg.js.map +1 -0
- package/dist/timeline/wrap.d.ts +7 -0
- package/dist/timeline/wrap.js +77 -0
- package/dist/timeline/wrap.js.map +1 -0
- package/dist/types.d.ts +96 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/package.json +57 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PRtape contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,139 @@
|
|
|
1
|
-
#
|
|
1
|
+
# PRtape
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
See what your AI agent actually did.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx prtape-cli pr
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
After a global install (`npm i -g prtape-cli`) the command is `prtape`.
|
|
12
|
+
|
|
13
|
+
- Reads the newest Claude Code session on your machine.
|
|
14
|
+
- Posts one redacted image on the pull request: files touched, tests, and the decision.
|
|
15
|
+
- Leaves the raw session off the PR.
|
|
16
|
+
|
|
17
|
+
## Happy path
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm i -g prtape-cli
|
|
21
|
+
npx prtape-cli pr
|
|
22
|
+
npx prtape-cli pr --dry-run
|
|
23
|
+
npx prtape-cli pr --json --dry-run
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Run it on the git branch that already has the pull request. One command, `npx prtape-cli pr`, reads the newest Claude Code session, posts a comment that leads with the timeline PNG, and does not ask you to upload anything yourself. `--dry-run` prints that comment and does not push or comment. If `gh` is missing, not authenticated, or the PNG push is denied, PRtape prints what failed and how to fix it, then uses a text timeline instead. It does not claim an image was posted.
|
|
27
|
+
|
|
28
|
+
From a checkout, before the package is on npm: `npx tsx src/cli.ts pr --dry-run`.
|
|
29
|
+
|
|
30
|
+
## What a reviewer sees
|
|
31
|
+
|
|
32
|
+
On the happy path the comment leads with the image, then the decision and a short table:
|
|
33
|
+
|
|
34
|
+
```markdown
|
|
35
|
+

|
|
36
|
+
|
|
37
|
+
**Ship the redacted timeline.**
|
|
38
|
+
|
|
39
|
+
| | |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| Files touched | `src/redact.ts` · `src/timeline/svg.ts` |
|
|
42
|
+
| Tests | yes · pass |
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Orphan ref
|
|
46
|
+
|
|
47
|
+
`prtape pr` builds a parentless commit whose tree is only `timeline.png`, using `git hash-object`, `git mktree`, and `git commit-tree` in a temp repository. It then runs:
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
git push origin +<commit>:refs/prtape/<head>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`<head>` is the SHA already on your branch. The new commit has no parent, and the destination is `refs/prtape/…`, not `refs/heads/…`, so it cannot merge into main and it is not your PR branch. The push does not update your index or working tree, and it does not create `.prtape/`. The tree contains `timeline.png` and nothing else. Running `prtape pr` again updates the latest PRtape comment on that pull request. A comment left by the previous AgentTape marker is updated in place instead of posting a second one.
|
|
54
|
+
|
|
55
|
+
The comment image is exactly:
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
https://github.com/<owner>/<repo>/raw/<commit>/timeline.png
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`<commit>` is the orphan commit that contains the PNG, not `raw.githubusercontent.com`. On a **public** repo, a logged-out viewer loading that `github.com/.../raw/<sha>/...` URL sees the image.
|
|
62
|
+
|
|
63
|
+
## Who can see the PNG
|
|
64
|
+
|
|
65
|
+
Visibility is not the same on public and private repos.
|
|
66
|
+
|
|
67
|
+
- **Public repo.** Anonymous viewers see the PNG at `github.com/.../raw/<sha>/...`.
|
|
68
|
+
- **Private repo.** Logged-out users, email notifications, and some mobile clients may show a broken image. Collaborators who can open the repo usually see it.
|
|
69
|
+
|
|
70
|
+
If `gh` is missing or not logged in, or the push to `refs/prtape/…` is denied, the command prints a one-glance error (what failed, and the fix) and posts or prints the text timeline only. That comment has no image URL.
|
|
71
|
+
|
|
72
|
+
## Redaction
|
|
73
|
+
|
|
74
|
+
On by default, before anything is rendered or posted:
|
|
75
|
+
|
|
76
|
+
| Pattern | Replaced with |
|
|
77
|
+
| --- | --- |
|
|
78
|
+
| `sk-ant-…` and other `sk-…` keys | `[REDACTED_API_KEY]` |
|
|
79
|
+
| GitHub tokens `ghp_`, `gho_`, `ghu_`, `ghs_`, `ghr_` | `[REDACTED_GITHUB_TOKEN]` |
|
|
80
|
+
| AWS access key ids (`AKIA` / `ASIA` / `AIDA` / `AROA`) and `AWS_SECRET_ACCESS_KEY=` values | `[REDACTED_AWS_KEY]` |
|
|
81
|
+
| Private IPv4 (`10/8`, `172.16/12`, `192.168/16`) and link-local | `[REDACTED_IP]` |
|
|
82
|
+
| Hostnames ending in `.internal` or `.local` | `[REDACTED_HOST]` |
|
|
83
|
+
|
|
84
|
+
Those spans are dropped from the pull-request comment, the timeline image, and the JSON fields a reviewer would read. The card does not print `[REDACTED_*]` or dotted stand-ins like `sk-••••`. Emails are left out of the title. `--redact-emails` also drops them from the rest of the summary. This is prefix matching, not a secret scanner.
|
|
85
|
+
|
|
86
|
+
## Sessions
|
|
87
|
+
|
|
88
|
+
Claude Code only for now. PRtape reads top-level `*.jsonl` under `~/.claude/projects` (or `$CLAUDE_CONFIG_DIR`). Subagent files are ignored. The timeline follows the newest leaf of the `uuid` / `parentUuid` tree so a rewind does not leak the abandoned branch. `thinking` blocks are never copied. The assumed line shape is documented in `src/adapters/claude.ts`; unknown fields and broken lines are skipped.
|
|
89
|
+
|
|
90
|
+
`--source claude` forces that reader. `--session <file>` skips discovery.
|
|
91
|
+
|
|
92
|
+
## Compared with ai-session
|
|
93
|
+
|
|
94
|
+
[ai-session](https://github.com/gammons/ai-session) archives the Claude Code transcript (scrubbed) in a side repo and links it from commits and a pull-request table. PRtape does not archive the transcript. It posts one redacted image — files touched, tests ran or not, and a one-line decision — so the review stays a glance. Redaction is on by default, and the raw session is not written into the working tree.
|
|
95
|
+
|
|
96
|
+
## Local development
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npm install
|
|
100
|
+
npm test
|
|
101
|
+
npx tsx src/cli.ts pr --dry-run --session fixtures/claude-session.jsonl
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Fixtures under `fixtures/` are synthetic. The strings that look like keys are canaries so tests can prove they never appear in the comment, the SVG, or the JSON.
|
|
105
|
+
|
|
106
|
+
The npm package name is `prtape-cli` (`bin` points at `dist/cli.js`). This checkout does not publish it.
|
|
107
|
+
|
|
108
|
+
## v0.2
|
|
109
|
+
|
|
110
|
+
Not in this release:
|
|
111
|
+
|
|
112
|
+
- A Claude Code `SessionEnd` hook that runs `prtape pr` when a session ends.
|
|
113
|
+
- Cursor session reading, planned for v0.2 alongside the Claude Code `SessionEnd` hook. v0.1 does not read Cursor transcripts.
|
|
114
|
+
- Still no `prepare-commit-msg` hook, and still no `.prtape/` directory in the repo.
|
|
115
|
+
|
|
116
|
+
## GitHub Action
|
|
117
|
+
|
|
118
|
+
There is no workflow in v0.1. Sessions live on the developer machine, so a hosted runner cannot see them. Notes: [docs/github-action.md](docs/github-action.md).
|
|
119
|
+
|
|
120
|
+
## 繁體中文
|
|
121
|
+
|
|
122
|
+
PRtape 把本機的 Claude Code 工作階段整理成一張預設已遮罩機密的 PR 圖,讓審查者大約五秒內看懂:動了哪些檔案、有沒有跑測試,以及一行決策摘要。目前只支援 Claude Code。
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
npx prtape-cli pr
|
|
126
|
+
npx prtape-cli pr --dry-run
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
原始工作階段不會寫進專案目錄。PNG 放在 `refs/prtape/<head>`,不會進 main。公開倉庫的未登入讀者也看得到 `github.com/.../raw/<sha>/timeline.png`;私人倉庫則不同,未登入、郵件通知與部分手機客戶端可能只看到破圖,有權限的協作者通常看得到。Cursor 支援與 Claude Code `SessionEnd` hook 留到 v0.2。
|
|
130
|
+
|
|
131
|
+
## FAQ
|
|
132
|
+
|
|
133
|
+
ASCII and mermaid appear only when the PNG was not pushed.
|
|
134
|
+
|
|
135
|
+
Tokens in square brackets in the fixture render are redaction markers, not real secrets.
|
|
136
|
+
|
|
137
|
+
## License
|
|
138
|
+
|
|
139
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { FALLBACK_DECISION, FALLBACK_TITLE } from "../types.js";
|
|
3
|
+
import { bashEvents, pathsInText, resolveReadGlobs } from "../bash-edits.js";
|
|
4
|
+
import { withSteps } from "../summary.js";
|
|
5
|
+
import { classifyTestOutput, parseTestCounts } from "../tests-detect.js";
|
|
6
|
+
import { oneLine } from "../text.js";
|
|
7
|
+
const FILE_EDIT_TOOLS = new Set([
|
|
8
|
+
"edit",
|
|
9
|
+
"multiedit",
|
|
10
|
+
"strreplace",
|
|
11
|
+
"notebookedit",
|
|
12
|
+
"search_replace",
|
|
13
|
+
]);
|
|
14
|
+
const FILE_WRITE_TOOLS = new Set(["write", "create", "notebookwrite"]);
|
|
15
|
+
const FILE_DELETE_TOOLS = new Set(["delete", "remove"]);
|
|
16
|
+
export function parseClaude(text, fallbackId = "claude-session") {
|
|
17
|
+
const records = parseLines(text);
|
|
18
|
+
const active = activeRecords(records);
|
|
19
|
+
const activeIds = new Set(active.map((record) => record.uuid).filter((id) => Boolean(id)));
|
|
20
|
+
const cwd = firstString(active, "cwd") ?? firstString(records, "cwd");
|
|
21
|
+
const branch = firstString(active, "gitBranch") ?? firstString(records, "gitBranch");
|
|
22
|
+
const sessionId = firstString(active, "sessionId") ?? firstString(records, "sessionId") ?? fallbackId.replace(/\.jsonl$/, "");
|
|
23
|
+
const startedAt = firstString(active, "timestamp");
|
|
24
|
+
const model = firstModel(active);
|
|
25
|
+
const prompts = [];
|
|
26
|
+
const assistantLines = [];
|
|
27
|
+
const seenTools = new Set();
|
|
28
|
+
const pending = [];
|
|
29
|
+
for (const record of active) {
|
|
30
|
+
if (record.isSidechain || record.isMeta)
|
|
31
|
+
continue;
|
|
32
|
+
if (record.type === "user") {
|
|
33
|
+
const prompt = humanPrompt(record);
|
|
34
|
+
if (prompt)
|
|
35
|
+
prompts.push(prompt);
|
|
36
|
+
}
|
|
37
|
+
if (record.type === "assistant") {
|
|
38
|
+
for (const block of contentBlocks(record.message?.content)) {
|
|
39
|
+
if (block.type === "text" && typeof block.text === "string" && block.text.trim()) {
|
|
40
|
+
assistantLines.push(block.text.trim());
|
|
41
|
+
}
|
|
42
|
+
if (block.type !== "tool_use")
|
|
43
|
+
continue;
|
|
44
|
+
const id = typeof block.id === "string" ? block.id : undefined;
|
|
45
|
+
const name = typeof block.name === "string" ? block.name : "";
|
|
46
|
+
const input = isRecord(block.input) ? block.input : {};
|
|
47
|
+
if (id && seenTools.has(id))
|
|
48
|
+
continue;
|
|
49
|
+
if (id)
|
|
50
|
+
seenTools.add(id);
|
|
51
|
+
pending.push(...toolEvents(name, input, cwd, id));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const results = collectToolResults(records);
|
|
56
|
+
const evidenced = [];
|
|
57
|
+
for (const result of results.values()) {
|
|
58
|
+
for (const filePath of pathsInText(result.text)) {
|
|
59
|
+
if (!evidenced.includes(filePath))
|
|
60
|
+
evidenced.push(filePath);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const events = resolveReadGlobs(pending.map((item) => resolveEvent(item, results)), evidenced);
|
|
64
|
+
const summaryText = pickSummary(records, activeIds);
|
|
65
|
+
const title = prompts[0] ? oneLine(prompts[0]) : FALLBACK_TITLE;
|
|
66
|
+
const decision = oneLine(summaryText || assistantLines.at(-1) || FALLBACK_DECISION);
|
|
67
|
+
return withSteps({
|
|
68
|
+
source: "claude-code",
|
|
69
|
+
sessionId,
|
|
70
|
+
startedAt,
|
|
71
|
+
model,
|
|
72
|
+
branch,
|
|
73
|
+
cwd,
|
|
74
|
+
title,
|
|
75
|
+
decision,
|
|
76
|
+
files: [],
|
|
77
|
+
tests: [],
|
|
78
|
+
events,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function toolEvents(name, input, cwd, toolId) {
|
|
82
|
+
const command = bashCommand(name, input);
|
|
83
|
+
if (command) {
|
|
84
|
+
const batch = toolId;
|
|
85
|
+
return bashEvents(command).map((event) => {
|
|
86
|
+
if (event.kind === "edit")
|
|
87
|
+
return { kind: "edit", path: displayPath(event.path, cwd), action: event.action, batch };
|
|
88
|
+
if (event.kind === "read")
|
|
89
|
+
return { kind: "read", path: event.path ? displayPath(event.path, cwd) : undefined, batch };
|
|
90
|
+
if (event.kind === "test")
|
|
91
|
+
return { kind: "test", command, toolId, batch };
|
|
92
|
+
return { kind: "commit", batch, message: event.message };
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
const tool = name.toLowerCase();
|
|
96
|
+
if (tool === "read" || tool === "view") {
|
|
97
|
+
const filePath = toolFilePath(input);
|
|
98
|
+
return [{ kind: "read", path: filePath ? displayPath(filePath, cwd) : undefined }];
|
|
99
|
+
}
|
|
100
|
+
const edit = fileEdit(tool, input, cwd);
|
|
101
|
+
return edit ? [edit] : [];
|
|
102
|
+
}
|
|
103
|
+
function resolveEvent(item, results) {
|
|
104
|
+
if (item.kind !== "test")
|
|
105
|
+
return item;
|
|
106
|
+
const result = item.toolId ? results.get(item.toolId) : undefined;
|
|
107
|
+
const outcome = result ? classifyTestOutput(result.text, result.isError, result.interrupted) : "unknown";
|
|
108
|
+
const counts = result ? parseTestCounts(result.text) : {};
|
|
109
|
+
return { kind: "test", command: item.command, outcome, batch: item.batch, ...counts };
|
|
110
|
+
}
|
|
111
|
+
function fileEdit(tool, input, cwd) {
|
|
112
|
+
const filePath = toolFilePath(input);
|
|
113
|
+
if (!filePath)
|
|
114
|
+
return undefined;
|
|
115
|
+
const path = displayPath(filePath, cwd);
|
|
116
|
+
const before = shortField(input, "old_string") ?? shortField(input, "old_str");
|
|
117
|
+
const after = shortField(input, "new_string") ?? shortField(input, "new_str");
|
|
118
|
+
const hunk = before && after ? { before, after } : {};
|
|
119
|
+
if (FILE_WRITE_TOOLS.has(tool))
|
|
120
|
+
return { kind: "edit", path, action: "write", ...hunk };
|
|
121
|
+
if (FILE_DELETE_TOOLS.has(tool))
|
|
122
|
+
return { kind: "edit", path, action: "delete" };
|
|
123
|
+
if (FILE_EDIT_TOOLS.has(tool))
|
|
124
|
+
return { kind: "edit", path, action: "edit", ...hunk };
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
function shortField(input, key) {
|
|
128
|
+
const value = input[key];
|
|
129
|
+
if (typeof value !== "string")
|
|
130
|
+
return undefined;
|
|
131
|
+
const trimmed = value.trim();
|
|
132
|
+
if (!trimmed || trimmed.length > 2000)
|
|
133
|
+
return undefined;
|
|
134
|
+
return trimmed;
|
|
135
|
+
}
|
|
136
|
+
function parseLines(text) {
|
|
137
|
+
const records = [];
|
|
138
|
+
for (const line of text.split(/\r?\n/)) {
|
|
139
|
+
const trimmed = line.trim();
|
|
140
|
+
if (!trimmed)
|
|
141
|
+
continue;
|
|
142
|
+
try {
|
|
143
|
+
const value = JSON.parse(trimmed);
|
|
144
|
+
if (isRecord(value))
|
|
145
|
+
records.push(value);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// Broken lines are ignored. Claude Code has changed this file before.
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return records;
|
|
152
|
+
}
|
|
153
|
+
function activeRecords(records) {
|
|
154
|
+
const withId = records.filter((record) => typeof record.uuid === "string" && record.uuid.length > 0);
|
|
155
|
+
if (withId.length === 0)
|
|
156
|
+
return records;
|
|
157
|
+
const byId = new Map();
|
|
158
|
+
const childCount = new Map();
|
|
159
|
+
for (const record of withId) {
|
|
160
|
+
byId.set(record.uuid, record);
|
|
161
|
+
}
|
|
162
|
+
for (const record of withId) {
|
|
163
|
+
const parent = record.parentUuid;
|
|
164
|
+
if (typeof parent === "string" && byId.has(parent)) {
|
|
165
|
+
childCount.set(parent, (childCount.get(parent) ?? 0) + 1);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const leaves = withId.filter((record) => (childCount.get(record.uuid) ?? 0) === 0);
|
|
169
|
+
leaves.sort((a, b) => String(b.timestamp ?? "").localeCompare(String(a.timestamp ?? "")));
|
|
170
|
+
const leaf = leaves[0];
|
|
171
|
+
if (!leaf?.uuid)
|
|
172
|
+
return records;
|
|
173
|
+
const pathRecords = [];
|
|
174
|
+
const seen = new Set();
|
|
175
|
+
let current = leaf;
|
|
176
|
+
while (current?.uuid && !seen.has(current.uuid)) {
|
|
177
|
+
pathRecords.push(current);
|
|
178
|
+
seen.add(current.uuid);
|
|
179
|
+
const parent = current.parentUuid;
|
|
180
|
+
current = typeof parent === "string" ? byId.get(parent) : undefined;
|
|
181
|
+
}
|
|
182
|
+
pathRecords.reverse();
|
|
183
|
+
// A broken parent chain would otherwise keep only the leaf.
|
|
184
|
+
if (pathRecords.length <= 1 && records.length > 2)
|
|
185
|
+
return records;
|
|
186
|
+
return pathRecords;
|
|
187
|
+
}
|
|
188
|
+
function pickSummary(records, activeIds) {
|
|
189
|
+
const summaries = records.filter((record) => record.type === "summary" && typeof record.summary === "string" && record.summary.trim());
|
|
190
|
+
const linked = summaries.find((record) => typeof record.leafUuid === "string" && activeIds.has(record.leafUuid));
|
|
191
|
+
const chosen = linked ?? summaries.at(-1);
|
|
192
|
+
return chosen?.summary?.trim();
|
|
193
|
+
}
|
|
194
|
+
function humanPrompt(record) {
|
|
195
|
+
const content = record.message?.content;
|
|
196
|
+
if (typeof content !== "string")
|
|
197
|
+
return undefined;
|
|
198
|
+
const text = content.trim();
|
|
199
|
+
return text || undefined;
|
|
200
|
+
}
|
|
201
|
+
function contentBlocks(content) {
|
|
202
|
+
if (!Array.isArray(content))
|
|
203
|
+
return [];
|
|
204
|
+
return content.filter(isRecord);
|
|
205
|
+
}
|
|
206
|
+
function toolFilePath(input) {
|
|
207
|
+
for (const key of ["file_path", "path", "notebook_path", "target_notebook", "filePath"]) {
|
|
208
|
+
const value = input[key];
|
|
209
|
+
if (typeof value === "string" && value.trim())
|
|
210
|
+
return value.trim();
|
|
211
|
+
}
|
|
212
|
+
return undefined;
|
|
213
|
+
}
|
|
214
|
+
function bashCommand(name, input) {
|
|
215
|
+
if (name.toLowerCase() !== "bash")
|
|
216
|
+
return undefined;
|
|
217
|
+
for (const key of ["command", "cmd"]) {
|
|
218
|
+
const value = input[key];
|
|
219
|
+
if (typeof value === "string" && value.trim())
|
|
220
|
+
return value.trim();
|
|
221
|
+
}
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
224
|
+
function collectToolResults(records) {
|
|
225
|
+
const results = new Map();
|
|
226
|
+
for (const record of records) {
|
|
227
|
+
if (record.isSidechain)
|
|
228
|
+
continue;
|
|
229
|
+
for (const block of contentBlocks(record.message?.content)) {
|
|
230
|
+
if (block.type !== "tool_result")
|
|
231
|
+
continue;
|
|
232
|
+
const id = stringOf(block, "tool_use_id");
|
|
233
|
+
if (!id || results.has(id))
|
|
234
|
+
continue;
|
|
235
|
+
const structured = structuredResult(record.toolUseResult);
|
|
236
|
+
const text = textOf(block.content) || structured.text;
|
|
237
|
+
results.set(id, {
|
|
238
|
+
text,
|
|
239
|
+
isError: Boolean(block.is_error) || structured.interrupted,
|
|
240
|
+
interrupted: structured.interrupted,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return results;
|
|
245
|
+
}
|
|
246
|
+
function structuredResult(value) {
|
|
247
|
+
if (!isRecord(value))
|
|
248
|
+
return { text: "", interrupted: false };
|
|
249
|
+
const stdout = typeof value.stdout === "string" ? value.stdout : "";
|
|
250
|
+
const stderr = typeof value.stderr === "string" ? value.stderr : "";
|
|
251
|
+
return {
|
|
252
|
+
text: [stdout, stderr].filter(Boolean).join("\n"),
|
|
253
|
+
interrupted: value.interrupted === true,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function textOf(content) {
|
|
257
|
+
if (typeof content === "string")
|
|
258
|
+
return content;
|
|
259
|
+
if (!Array.isArray(content))
|
|
260
|
+
return "";
|
|
261
|
+
return content
|
|
262
|
+
.map((part) => {
|
|
263
|
+
if (typeof part === "string")
|
|
264
|
+
return part;
|
|
265
|
+
if (!isRecord(part))
|
|
266
|
+
return "";
|
|
267
|
+
if (typeof part.text === "string")
|
|
268
|
+
return part.text;
|
|
269
|
+
if (typeof part.content === "string")
|
|
270
|
+
return part.content;
|
|
271
|
+
return "";
|
|
272
|
+
})
|
|
273
|
+
.join("\n");
|
|
274
|
+
}
|
|
275
|
+
function displayPath(filePath, cwd) {
|
|
276
|
+
let out = filePath;
|
|
277
|
+
if (cwd && path.isAbsolute(filePath)) {
|
|
278
|
+
const relative = path.relative(cwd, filePath);
|
|
279
|
+
if (relative && !relative.startsWith("..") && !path.isAbsolute(relative)) {
|
|
280
|
+
out = relative;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return out.split(path.sep).join("/");
|
|
284
|
+
}
|
|
285
|
+
function firstString(records, key) {
|
|
286
|
+
for (const record of records) {
|
|
287
|
+
const value = record[key];
|
|
288
|
+
if (typeof value === "string" && value.trim())
|
|
289
|
+
return value;
|
|
290
|
+
}
|
|
291
|
+
return undefined;
|
|
292
|
+
}
|
|
293
|
+
function firstModel(records) {
|
|
294
|
+
for (const record of records) {
|
|
295
|
+
const model = record.message?.model;
|
|
296
|
+
if (typeof model === "string" && model.trim())
|
|
297
|
+
return model.trim();
|
|
298
|
+
}
|
|
299
|
+
return undefined;
|
|
300
|
+
}
|
|
301
|
+
function stringOf(value, key) {
|
|
302
|
+
const record = value;
|
|
303
|
+
const found = record[key];
|
|
304
|
+
return typeof found === "string" && found.trim() ? found : undefined;
|
|
305
|
+
}
|
|
306
|
+
function isRecord(value) {
|
|
307
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
308
|
+
}
|
|
309
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/adapters/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { TimelineEvent } from "./types.js";
|
|
2
|
+
export interface BashEdit {
|
|
3
|
+
path: string;
|
|
4
|
+
action: "edit" | "write";
|
|
5
|
+
}
|
|
6
|
+
export type BashEvent = {
|
|
7
|
+
kind: "read";
|
|
8
|
+
path?: string;
|
|
9
|
+
} | {
|
|
10
|
+
kind: "edit";
|
|
11
|
+
path: string;
|
|
12
|
+
action: "edit" | "write";
|
|
13
|
+
} | {
|
|
14
|
+
kind: "test";
|
|
15
|
+
} | {
|
|
16
|
+
kind: "commit";
|
|
17
|
+
message?: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Project files a Bash command writes, conservatively.
|
|
21
|
+
* Counts in-place `sed -i` / `perl -i` and unquoted `>` / `>>` into the project.
|
|
22
|
+
* Does not count reads, `tee` log capture, or scratch paths.
|
|
23
|
+
*/
|
|
24
|
+
export interface BashSubstitution {
|
|
25
|
+
file: string;
|
|
26
|
+
old: string;
|
|
27
|
+
next: string;
|
|
28
|
+
}
|
|
29
|
+
/** In-place `sed` replacements, in command order. Used to describe what the edit changed. */
|
|
30
|
+
export declare function bashSubstitutions(command: string): BashSubstitution[];
|
|
31
|
+
export declare function bashFileEdits(command: string): BashEdit[];
|
|
32
|
+
/**
|
|
33
|
+
* Left-to-right actions inside one Bash command.
|
|
34
|
+
* Reads joined with `;` or `&&` before a test stay, in order.
|
|
35
|
+
* A pipe into the test (`cat x | npm test`) is setup, not its own beat.
|
|
36
|
+
*/
|
|
37
|
+
export declare function bashEvents(command: string): BashEvent[];
|
|
38
|
+
/** Repo-relative paths printed in tool output, such as `ls` lines or `cat` file headers. */
|
|
39
|
+
export declare function pathsInText(text: string): string[];
|
|
40
|
+
/** Expand a simple `*` / `?` read against concrete paths evidenced in the session. */
|
|
41
|
+
export declare function resolveReadGlobs(events: TimelineEvent[], extra?: string[]): TimelineEvent[];
|